package com.fastloan.mgt.application.download;

import com.fastloan.mgt.application.approve.service.ApplicationApproveFileService;
import com.fastloan.mgt.application.base.model.Application;
import com.fastloan.mgt.application.base.service.ApplicationIPCService;
import com.fastloan.mgt.application.base.service.ApplicationService;
import com.fastloan.mgt.application.contract.service.ApplicationContractService;
import com.fastloan.mgt.application.phoneapprove.service.ApplicationPhoneApproveService;
import com.fastloan.mgt.customer.model.ZyCustomer;
import com.fastloan.mgt.customer.service.ZyCustomerService;
import com.fastloan.safe.mgt.sys.service.CmSysFileService;
import com.kawins.supers.file.IFileManager;
import com.kawins.util.file.ZipUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import static com.kawins.util.file.FileUtil.buildOsPath;
import static java.util.stream.Collectors.toList;

/**
 * @author chenkai
 * createTime 2017-11-2017/11/28 10:38
 */
@Component
public class DownloadFileToZip {
    @Autowired
    private IFileManager fileManager;

    @Autowired
    private CmSysFileService cmSysFileService;

    @Autowired
    private ApplicationApproveFileService applicationApproveFileService;

    @Autowired
    private ApplicationPhoneApproveService applicationPhoneApproveService;

    @Autowired
    private ApplicationContractService applicationContractService;

    @Autowired
    private ApplicationIPCService applicationIPCService;

    @Autowired
    private ApplicationService applicationService;

    @Autowired
    private ZyCustomerService customerService;


    /**
     * 下载进件文件
     *
     * @param applicationId
     * @param request
     * @param response
     * @throws IOException
     */
    public void download(String applicationId, HttpServletRequest request, HttpServletResponse response) throws IOException {
        //专家审批信息
        Map<String, List<String>> map = new HashMap<>();
        List<String> approveFileIds = applicationApproveFileService.getApproveFileIds(applicationId);
        if (!approveFileIds.isEmpty()) {
            map.put("专家审批", approveFileIds);
        }
        List<String> queryFileIds = applicationPhoneApproveService.queryFileIds(applicationId);
        if (!queryFileIds.isEmpty()) {
            map.put("电核", queryFileIds);
        }
        List<String> contractFileIds = applicationContractService.queryContractFileIds(applicationId);
        if (!contractFileIds.isEmpty()) {
            map.put("签约", contractFileIds);
        }
        map.putAll(applicationIPCService.queryFileIds(applicationId));
        downApplicationFile(applicationId, map, request, response);
    }

    /**
     * @param applicationId 进件id
     * @param map
     * @param request
     * @param response
     */
    public void downApplicationFile(String applicationId, Map<String, List<String>> map, HttpServletRequest request, HttpServletResponse response) {
        if (!map.isEmpty()) {
            map.forEach((dir, fileIdList) -> {
                if (fileIdList != null && !fileIdList.isEmpty()) {
                    List<FileTempBean> tempBeamList = fileIdList.stream()
                            .map(cmSysFileService::selectByPrimaryKey)
                            .filter(Objects::nonNull)
                            .map(cmSysFile -> {
                                FileTempBean fileTempBeam = new FileTempBean();
                                fileTempBeam.setInputStream(fileManager.downloadStream(cmSysFile.getId()));
                                fileTempBeam.setFileName(cmSysFile.getFileName());
                                return fileTempBeam;
                            }).collect(toList());
                    tempBeamList.stream()
                            .filter(Objects::nonNull)
                            .forEach(fileTempBeam -> {
                                try {
                                    writeFile(fileTempBeam.getInputStream(), getFileDir(applicationId, dir, request, fileTempBeam));
                                } catch (IOException e) {
                                    e.printStackTrace();
                                }
                            });
                }
            });
            writePdf(applicationId, request);
            String zipPath = request.getServletContext()
                    .getRealPath(File.separator + "WEB-INF" + File.separator + "temp" + File.separator + applicationId + File.separator);
            breakZip(response, zipPath, applicationId);
        }
    }


    /**
     * 写入文件
     *
     * @param InputStream
     * @param readPath
     */
    private static void writeFile(InputStream InputStream, String readPath) {
        FileOutputStream outputStream = null;
        try {
            outputStream = new FileOutputStream(new File(readPath));
            IOUtils.write(IOUtils.toByteArray(InputStream), outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(InputStream);
            IOUtils.closeQuietly(outputStream);
        }
    }

    private void writePdf(String applicationId, HttpServletRequest request) {
        FileOutputStream outputStream = null;
        try {
            String readPath = request.getServletContext()
                    .getRealPath(File.separator + "WEB-INF" + File.separator + "temp" + File.separator + applicationId + File.separator + "进件.pdf");
            outputStream = new FileOutputStream(new File(readPath));
            applicationService.createApplicationPDF(applicationId, outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(outputStream);
        }
    }

    /**
     * 压缩文件并下载
     *
     * @param response
     * @param finalPath
     * @param applicationId
     */
    private void breakZip(HttpServletResponse response, String finalPath, String applicationId) {
        response.setContentType("APPLICATION/OCTET-STREAM");
        Application application = applicationService.selectByPrimaryKey(applicationId);
        ZyCustomer customer = customerService.selectByPrimaryKey(application.getCustomerId());
        String zipName = customer.getCname() + "_" + application.getApplicationCode();
        ZipOutputStream out = null;
        try {
            response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(zipName, "UTF-8") + ".zip");
            out = new ZipOutputStream(response.getOutputStream());
            ZipUtils.doCompress(finalPath, out);
            response.flushBuffer();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            deleteDir(new File(finalPath));
            IOUtils.closeQuietly(out);
        }
    }

    /**
     * 创建文件路径
     *
     * @param applicationId
     * @param dir
     * @param request
     * @param fileTempBeam
     * @return
     */
    private String getFileDir(String applicationId, String dir, HttpServletRequest request, FileTempBean fileTempBeam) throws IOException {
        String fileName = fileTempBeam.getFileName();
        String readPath = request.getServletContext()
                .getRealPath(File.separator + "WEB-INF" + File.separator + "temp" + File.separator + applicationId);
        if (!StringUtils.isBlank(dir)) {
            readPath = readPath + File.separator + dir + File.separator;
        }
        String fileDir = readPath.substring(0, readPath.lastIndexOf(File.separator));
        File fileSub = new File(fileDir);
        if (!fileSub.exists() && !fileSub.isDirectory()) {
            mkDir(fileDir);
        }
        return readPath + fileName;

    }

    /**
     * 创建文件
     *
     * @param dirPath
     */
    private static void mkDir(String dirPath) {
        File myFolderPath = new File(buildOsPath(dirPath));
        try {
            if (!myFolderPath.exists()) {
                myFolderPath.mkdirs();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除文件和子文件夹
     *
     * @param dir
     * @return
     */
    private boolean deleteDir(File dir) {
        if (dir.isDirectory()) {
            String[] children = dir.list();
            for (int i = 0; i < children.length; i++) {
                boolean success = deleteDir(new File(dir, children[i]));
                if (!success) {
                    return false;
                }
            }
        }
        return dir.delete();
    }

    private static void ZipToStream(OutputStream outputStream, InputStream fileInputStream, String FileName, String outDir) {
        ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream);
        try {
            ZipEntry zipEntry = new ZipEntry(outDir);
            zipOutputStream.putNextEntry(zipEntry);
            zipOutputStream = new ZipOutputStream(new FileOutputStream(new File(FileName)));
            IOUtils.write(IOUtils.toByteArray(fileInputStream), zipOutputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            IOUtils.closeQuietly(fileInputStream);
            IOUtils.closeQuietly(zipOutputStream);
        }
    }
}


class FileTempBean {
    private String fileName;
    private InputStream inputStream;

    String getFileName() {
        return fileName;
    }

    void setFileName(String fileName) {
        this.fileName = fileName;
    }

    InputStream getInputStream() {
        return inputStream;
    }

    void setInputStream(InputStream inputStream) {
        this.inputStream = inputStream;
    }
}